/*
 * Assistant.java
 * Copyright (c)  kecp
 */

package traveller;

import LBS.AddressSrv;
import LBS.EricssonLBS;
import LBS.GoogleLBS;
import LBS.GoogleMap;
import LBS.LocApiComLBS;
import LBS.Location;
import Tool.Debugger;
import java.util.Vector;
import javax.microedition.lcdui.Image;

/**
 * 旅游助手
 * 处理应用程序逻辑，与界面进行交互
 * @author kecp
 */
public class Assistant implements TravelListener{
    GoogleMap gogmap;
    Traveller trav;
    Alarm alarm;
 //   Address destAddr;
    AddressSrv addrSrv;


    final byte TS_WATCHING = 1;
    final byte TS_ARRIVED = 2;
    final byte TS_IDLE  = 3;
    private byte travState = TS_IDLE;


    /**
     * 位置更新模式:停止位置更新
     */
    final byte WT_WAIT = 0x0;
    /**
     * 位置更新模式：运行，定时执行位置更新
     */
    final byte WT_RUN = 0x1;
    /**
     * 位置更新模式：即刻执行一次位置更新
     */
    final byte WT_IMMEDIATELY = 0x1<<1;
    /**
     * 当前位置更新模式
     */
    private byte watchType = WT_WAIT;
    /**
     * 用于同步位置更新
     */
    private final Object watchObj = new Object();

    /**
     * 位置更新线程
     */
    private Thread updateThread = null;

    TravelListener travListen;

    private static Assistant theAssistant = null;

    /**
     * 获取助手单例
     * @return
     */
    static public Assistant getTheAssistant() {
        if( theAssistant ==null ) {
            theAssistant = new Assistant();
        }
        return theAssistant;
    }

    private Assistant() {
        gogmap = new GoogleMap();
       //  trav = new Traveller( new LocApiComLBS());
      //  trav = new Traveller( new EricssonLBS());
         trav = new Traveller( new GoogleLBS());
        trav.range = 1000;
        alarm = new Alarm();
        addrSrv = new AddressSrv();

    }

    public void setTravelListener( TravelListener tral ) {
        travListen = tral;
    }

    public Image getCurMap() {
        Location curLoct = trav.getCur();
        if( curLoct == null ) {
           trav.updateCurLoct();
           curLoct = trav.getCur();
        }

        if( curLoct == null ) {
            Debugger.addDebugInfo("cann't get the current location");
            return null;
        }

        return gogmap.getImg(curLoct);
    }
    
    public Vector searchAddress( String addressKey ) {
        addrSrv.searchLocation(addressKey);
        return addrSrv.getCurLocts();
    }

//    void setDestAddr( Address adrs ) {
//        destAddr = adrs;
//        if( destAddr.loct == null ) {
//            addrSrv.searchLocation(destAddr.address);
//        }
//        curChanged();
//    }

    public void setDestLocation( Location loct ) {
     //   destAddr.address = loct.getName();
     //   destAddr.loct = loct;
        trav.dest = loct;
        destChanged(loct);
    }

     public void setCurLocation( Location loct ) {
        trav.setCur(loct);
     }

    public Location getCurLoct() {
        return trav.getCur();
    }

    public Location getDestLoct() {
        return trav.dest;
    }

    /**
     * 开始监视目的地
     * @return
     */
    public boolean beginWatch () {
        synchronized( watchObj ) {
            watchType &= ~WT_WAIT;
            watchType |= WT_RUN;
        }
        updateCurLoct();
        return true;
    }

    /**
     * 停止监视
     * @return
     */
    public boolean stopWatch() {
        setTravState( TS_IDLE) ;
          synchronized( watchObj ) {
            watchType &= ~WT_RUN;
            watchType |= WT_WAIT;
        }
        return true;
    }

    
    /**
     * 创建并运行更新当前位置的线程
     */
    public void createUpdateThrd() {
        if( updateThread == null ) {
            updateThread =  new Thread() {
                    public void run() {

                        //线程定时执行函数体,或者当函数被调用执行
                        while(true)
                        {
                           boolean excute = false;
                           synchronized( watchObj ) {
                                try {
                                    if( (watchType & WT_IMMEDIATELY) != 0  ) {
                                        excute = true;
                                        watchType &= ~WT_IMMEDIATELY;
                                    }
                                    else if( ( watchType & WT_RUN ) == 0  ){
                                        watchObj.wait();
                                        continue;
                                    }
                                    else {
                                          watchObj.wait(1000000); //定时时间
                                          watchType |= WT_IMMEDIATELY; //转为即刻更新
                                          continue;
                                          //excute = true;
                                    }
                                    //执行位置更新
                                    if( excute ) {
                                        if( trav.updateCurLoct() == true ) {
                                            Location loct = trav.getCur();
                                            if( loct!=null ) {
                                                //取得当前的地点名
                                                String addr = addrSrv.addressLookup(loct);
                                                loct.setName(addr);
                                            }
                                            //通知位置改变事件
                                            curChanged(loct);
                                        }
                                        
                                    }
                               //     Debugger.addDebugInfo("updateCurLoct");

                                } catch (InterruptedException ex) {
                                    ex.printStackTrace();
                                }
                        }
                    }
                } };
            updateThread.start();
        }
    }

    /**
     * 更新当前位置,第一次调用时生成定时更新的线程
     */
    public void updateCurLoct() {
        if( updateThread == null ) {
           watchType |= WT_IMMEDIATELY;
           createUpdateThrd();
        }
        else{
            //唤醒线程，执行更新
            synchronized( watchObj ) {
                watchType |= WT_IMMEDIATELY;
                watchObj.notify();
            }
        }
    }

    /**
     * @return 当前位置到目的位置的距离
     */
    public int getDistance() {
        return trav.getDistance();
    }

    protected void setTravState( byte ts ) {
        switch( ts ) {

        case TS_IDLE:
            travState = ts;
            break;
        case TS_WATCHING:
                if( ts == TS_ARRIVED )
                     alarm.play();
                travState = ts;
            break;
        case TS_ARRIVED:
            if( ts == TS_IDLE )
                alarm.stop();
                break;
        }
    }

    public void destChanged(Location dest) {
        travListen.destChanged(dest);
    }

    public void curChanged(Location cur) {
        if( trav.isInRange() ) {
           setTravState( TS_ARRIVED );
        }
        travListen.curChanged(cur);
    }
}
